/*
 * @Author: jianfanfan 是是是
 * @Date: 2025-09-04 16:03:13
 * @LastEditors: jianfanfan 是是是
 * @LastEditTime: 2025-09-17 15:51:03
 * @FilePath: \nest-project\src\app.controller.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import {
  Controller,
  Get,
  Post,
  Body,
  HttpException,
  HttpStatus,
  Inject,
  Query,
  UseFilters,
  UseGuards,
  UseInterceptors,
  Headers,
  SetMetadata,
  ParseIntPipe,
  ParseFilePipe,
  ParseFloatPipe,
  ParseArrayPipe,
  UploadedFile,
  UploadedFiles,
  MaxFileSizeValidator,
  FileTypeValidator,
  Logger,
} from '@nestjs/common';
import { AppService } from './app.service';
import { LoginGuard } from './login.guard';
import { TimeInterceptor } from './time.interceptor';
import { ValidatePipe } from './validate.pipe';
import { TestFilter } from './test.filter';
import { AaaGuard } from './aaa.guard';
import { AaaFilter } from './aaa.filter';
import { AAAException } from './aaaException';
import { Roles } from './roles.decorator';
import { Role } from './role';
import { MpTestInterceptor } from './mp-test.interceptor';
import { TapTestInterceptor } from './tap-test.interceptor';
import { CatchErrorTestInterceptor } from './catch-error-test.interceptor';
import { TimeoutInterceptor } from './timeout.interceptor';
import type { AaaDto } from './aaa.dto';
import {
  AnyFilesInterceptor,
  FileInterceptor,
  FilesInterceptor,
} from '@nestjs/platform-express';
import { storage } from './storage';
import { FileSizeValidationPipe } from './file-size-validation-pipe.pipe';
import fs from 'fs';

@Controller()
export class AppController {
  private logger = new Logger();
  constructor(
    @Inject('app_service') private readonly appService: AppService,
    @Inject('person') private readonly person: { name: string; age: number },
    @Inject('person2') private readonly person2: { name: string; age: number },
  ) {}

  @Get()
  //   @SetMetadata('aaa', 'admin')
  //   @UseGuards(AaaGuard)
  //   @UseFilters(AaaFilter)
  //   @Roles(Role.Admin)
  getHello(
    @Query(
      'name',
      new ParseArrayPipe({
        items: Number,
        // separator: ',',
      }),
      //   new ParseIntPipe({
      //     exceptionFactory: (msg) => {
      //       console.log(msg);
      //       throw new HttpException('xxx' + msg, HttpStatus.BAD_REQUEST);
      //     },
      //   }),
    )
    name: Array<number>,
  ): number {
    // throw new AAAException('aaa', 'bbb');
    throw new HttpException('xxx', HttpStatus.BAD_REQUEST);
    return name.reduce((total, item) => total + item, 0);
  }

  @Post('upload')
  @UseInterceptors(
    FilesInterceptor('files', 20, {
      dest: 'uploads',
    }),
  )
  uploadFiles(
    @UploadedFiles() files: Array<Express.Multer.File>,
    @Body() body: { name: string },
  ) {
    console.log('body', body);
    console.log('files', files);
    if (!files || files.length === 0) {
      throw new HttpException('No files uploaded', HttpStatus.BAD_REQUEST);
    }

    const match = body?.name?.match(/(.+)\-\d+$/);
    const fileName = match ? match[1] : (body?.name ?? 'unknown');
    const chunkDir = 'uploads/chunks_' + fileName;

    if (!fs.existsSync(chunkDir)) {
      fs.mkdirSync(chunkDir);
    }
    fs.cpSync(files[0].path, chunkDir + '/' + body.name);
    fs.rmSync(files[0].path);
  }

  @Get('merge')
  merge(@Query('name') name: string) {
    const chunkDir = 'uploads/chunks_' + name;

    const files = fs.readdirSync(chunkDir);

    let count = 0;
    let startPos = 0;
    files.map((file) => {
      const filePath = chunkDir + '/' + file;
      const stream = fs.createReadStream(filePath);
      stream
        .pipe(
          fs.createWriteStream('uploads/' + name, {
            start: startPos,
          }),
        )
        .on('finish', () => {
          count++;

          if (count === files.length) {
            fs.rm(
              chunkDir,
              {
                recursive: true,
              },
              () => {},
            );
          }
        });

      startPos += fs.statSync(filePath).size;
    });
  }

  @Get('hello2')
  getHello2(): string {
    console.log('hello2');
    return this.appService.getHello();
  }

  @Get('hello3')
  getHello3(): string {
    console.log('hello3');
    return this.appService.getHello();
  }

  @Get('aaa')
  //   @UseGuards(LoginGuard)
  //   @UseInterceptors(MpTestInterceptor)
  aaa(): string {
    return 'aaa';
  }

  @Post('aaa')
  @UseInterceptors(FileInterceptor('aaa', { dest: 'uploads' }))
  uploadFile(@UploadedFile() file: Express.Multer.File, @Body() body: any) {
    console.log('body', body);
    console.log('file', file);
  }

  @Get('bbb')
  @UseInterceptors(TapTestInterceptor)
  bbb(): string {
    return 'bbb';
  }

  //   @Post('bbb')
  //   @UseInterceptors(FileInterceptor('aaa', { dest: 'uploads' }))
  //   uploadFiles(
  //     @UploadedFile(
  //       new ParseFilePipe({
  //         exceptionFactory: (error) => {
  //           throw new HttpException('xxx' + error, 404);
  //         },
  //         validators: [
  //           new MaxFileSizeValidator({ maxSize: 1000 }), // 10MB
  //           new FileTypeValidator({ fileType: 'image/jpeg' }),
  //         ],
  //       }),
  //     )
  //     file: Express.Multer.File,
  //     @Body() body,
  //   ) {
  //     console.log('body', body);
  //     console.log('files', file);
  //   }

  @Get('ccc')
  @UseFilters(TestFilter)
  ccc(@Query('num', ValidatePipe) num: number) {
    return num + 1;
  }

  @Get('ddd')
  header(
    @Headers('Accept') accept: string,
    @Headers() headers: Record<string, any>,
  ) {
    console.log(accept, headers);
  }

  @Get('eee')
  @UseInterceptors(CatchErrorTestInterceptor)
  eee(): string {
    // throw new Error('error');
    return 'eee';
  }

  @Get('fff')
  //   @UseInterceptors(TimeoutInterceptor)
  async fff() {
    await new Promise((resolve) => {
      setTimeout(resolve, 5000);
    });
    return 'fff';
  }

  @Post('ggg')
  ggg(@Body() aaaDto: AaaDto) {
    return 'success';
  }
}
